<!-- 设置角色权限 -->
<template>
    <div class="vue-box sbot" style="width: 800px; height: 600px; ">
        <!-- ------- 内容部分 ------- -->
        <div class="s-body">
            <!-- 表格 -->
            <div style="padding: 1em 2em;">
                <el-form>
                    <div class="c-title">所有菜单</div>
                    <!-- 此扩展能递归渲染一个权限树，点击深层次节点，父级节点中没有被选中的节点会被自动选中，单独点击父节点，子节点会全部 选中/去选中 -->
                    <el-tree
                        ref="tree"
                        :data="state.dataList"
                        show-checkbox
                        node-key="id"
                        :default-expand-all="true"
                        :default-checked-keys="state.selectList"
                        :expand-on-click-node="false"
                        :check-on-click-node="true"
                        :check-strictly="true"
                        @node-click="nodeClick"
                        @check="nodeClick"
                    >
                        <template #default="s">
                            <span class="custom-tree-node">
                                <span v-if="s.data.show === 'yes'" style="color: green;">{{ s.data.title }} &nbsp; [ 永远显示 ]</span>
                                <span v-else-if="s.data.show === 'no'" style="color: #999;">{{ s.data.title }} &nbsp; [ 永远隐藏 ]</span>
                                <span v-else style="color: #2D8CF0;">{{ s.data.title }} &nbsp; [ 鉴权显示 ]</span>
                                <span style="color: #999;" v-if="s.data.info">&emsp;———— {{ s.data.info }} </span>
                            </span>
                        </template>
                    </el-tree>
                </el-form>
            </div>
        </div>
        <!-- ------- 底部按钮 ------- -->
        <div class="s-foot">
            <el-button type="success" @click="checkedAll()">全选</el-button>
            <el-button type="primary" @click="ok()">确定</el-button>
            <el-button @click="sa.closeModel()">取消</el-button>
        </div>
    </div>
</template>

<script setup name="menu-setup">
import {getCurrentInstance, onMounted, reactive} from "vue";
import {arrayToTree, defineMenu} from "../../router/router-util";
import {useMenuList} from "../../router";
import {useSettingStore} from "../../store/setting";
const settingStore = useSettingStore();
const {proxy} = getCurrentInstance();

// 获取插槽信息 
const prop = defineProps({
    param: Object
})

// ------------------ 数据 ------------------
const state = reactive({
    isServerMenu: settingStore.isServerMenu, // 是否从后端加载菜单 
    roleId: prop.param.roleId,   // 角色id 
    dataList: [],   // 菜单列表 
    selectList: [],   // 默认选中 
    ywList: [],   // 一维数组 
    haveList: [],   // 这个角色用的权限id，拷贝（用于计算是否修改掉了关键属性）
})

onMounted(() => {
    // 后端模式
    if(state.isServerMenu) {
        sa.ajax('/SpMenu/getList', function(res){
            state.dataList = arrayToTree(defineMenu(res.data));
            state.ywList = treeToArray(state.dataList);
        });
    } else {
        // 前端模式
        state.dataList = sa.copyArray(useMenuList());
        state.ywList = treeToArray(state.dataList);
    }
    
    // 拉取此 roleId 具有的所有权限
    sa.ajax('/SpRolePermission/getPcodeByRid?roleId=' + state.roleId, function(res) {
        state.selectList = res.data;		// 选中的列表
        state.haveList = sa.copyArray(state.selectList);
    })
});

// 保存
const ok = function(clickCount){
    if (clickCount === undefined) {
        clickCount = 5;
    }
    // 判断是否改掉了关键权限
    const keys = proxy.$refs.tree.getCheckedKeys();		// 设置完拥有的id列表
    const rArr = ['root', 'in-system', 'auth', 'role-list'];		// 敏感菜单id列表
    let isR = false;									// 是否给改掉了
    rArr.forEach(function(item) {
        // 只有原先有，现在没有，才会被这样判定
        if (state.haveList.indexOf(item) > -1 && keys.indexOf(item) === -1) {
            isR = true;
        }
    })
    // 高危操作的提示
    if (isR) {
        let tipStr = '<p style="max-width: 400px">危险！系统检测到您取消了此角色的重要权限，这将导致与之关联的账号可能会无法正常使用后台，您无论如何都要这样设置吗？</p>';
        tipStr += '<br/>为保证您不是误操作，您还需要继续点击按钮: ' + clickCount + '次'
        tipStr = '<b style="color: red;">' + tipStr + '</b>';
        sa.confirm(tipStr, { isHtmlFragment: true }, function(res) {
            if (clickCount <= 1) {
                ok2();
            } else {
                clickCount--;
                ok(clickCount);
            }
        })
    } else {
        ok2();
    }
};
// 真正的保存
const ok2 = function() {
    const keys = proxy.$refs.tree.getCheckedKeys()
    const url = '/SpRolePermission/updatePcodeByRid'
    sa.ajax(url, {roleId: state.roleId, codes: keys.join(',')}, function(res) {
        sa.alert('设置成功', function(){
            sa.closeModel();
        });
        // 如果设置的角色与当前登录者的角色一致，则立即显示出来
        // console.log(this.roleId)
        // console.log(sa.$sys.getCurrUser().roleId)
        if (state.roleId === sa.$sys.getCurrUser().roleId) {
            sa.setAuth(keys);
            // UI立刻显现
            // console.log('xxxx')
            // this.$store.commit('permission/setPerCodes', keys);
        }
    })
};
// 点击回调, 处理其子节点跟随父节点的选中
const nodeClick = function(node) {
    // console.log(node)
    const isSelect = proxy.$refs.tree.getCheckedKeys().indexOf(node.id) !== -1;	// 此节点现在是否被选中
    if (node.children){
        node.children.forEach(function(item) {
            proxy.$refs.tree.setChecked(item.id, isSelect);
            // 递归
            if (item.children) {
                nodeClick(item);
            }
        })
    }
};
// 全选/ 取消全选
const checkedAll = function() {
    if (proxy.$refs.tree.getCheckedKeys().length !== state.ywList.length) {
        proxy.$refs['tree'].setCheckedNodes(state.ywList);
    } else {
        proxy.$refs['tree'].setCheckedNodes([]);
    }
};
// 将 Tree 菜单 转换为 一维平面数组
const treeToArray = function(menuList) {
    let arr = [];
    function _dg(_menuList) {
        _menuList = _menuList || [];
        for (let i = 0; i < _menuList.length; i++) {
            let menu = _menuList[i];
            arr.push(menu);
            // 如果有子菜单
            if (menu.children) {
                _dg(menu.children);
            }
        }
    }
    _dg(menuList);
    return arr;
};


</script>

<style scoped lang="scss">
.vue-box{
    /* 调整一下样式 */
    :deep(.el-tree-node) {padding: 0 !important;}
    :deep(.el-tree-node__content) {
        height: 30px; line-height: 32px; overflow: hidden;
        .custom-tree-node{height: 32px;}
        &:hover{
            background-color: #CFE8FC !important;
        }
    }
    :deep(.el-tree-node__label){width: 100%;}
}
</style>
